package com.jintian.smart.kernel.module.impl;

import com.jintian.smart.kernel.module.Model;
import com.jintian.smart.kernel.module.config.BeetlTemplateElementScanner;
import org.beetl.core.GroupTemplate;
import org.beetl.core.resource.ClasspathResourceLoader;
import org.beetl.ext.spring6.BeetlGroupUtilConfiguration;
import org.beetl.ext.spring6.BeetlSpringViewResolver;
import org.beetl.sql.ext.spring.BeetlSqlClassPathScanner;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * model加载时强制关闭了beetl的自动装配，这里手动进行装配
 */
public class ModelBeetlProcessor implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware {
    final Model model;
    ApplicationContext applicationContext;

    public ModelBeetlProcessor(Model model) {
        this.model = model;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        {
            // 1.注册BeetlGroupUtilConfiguration
            BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(BeetlGroupUtilConfiguration.class);
            bdb.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            Properties extProperties = new Properties();
            if (model.isDev()) {
                extProperties.put("RESOURCE.autoCheck", "true");
            } else {
                extProperties.put("RESOURCE.autoCheck", "false");
            }
            bdb.addPropertyValue("configProperties", extProperties);
            ClasspathResourceLoader cploder = new ClasspathResourceLoader(this.model.getClassLoader(), this.model.getBeetlTemplatesPath());
            bdb.addPropertyValue("resourceLoader", cploder);
            bdb.setInitMethodName("init");
            registry.registerBeanDefinition("beetlConfig", bdb.getBeanDefinition());
        }

        {
            // 2.注册BeetlSpringViewResolver，用于创建BeetlSpringView
            BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(BeetlSpringViewResolver.class);
            bdb.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            bdb.addPropertyValue("contentType", "text/html;charset=UTF-8");
            // ajax 支持
            bdb.addPropertyValue("viewNames", new String[]{"*." + this.model.getBeetlViewSuffix(), "*." + this.model.getBeetlViewSuffix() + "#*"});
            bdb.addPropertyValue("order", 0);
            bdb.addPropertyReference("config", "beetlConfig");
            registry.registerBeanDefinition("beetlViewResolver", bdb.getBeanDefinition());
        }

        {
            // 3.注册GroupTemplate
            BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(GroupTemplate.class);

            Map<String, Object> sharedVars = new HashMap<>(5);
            sharedVars.put("appName", model.getName());
            sharedVars.put("jsVer", model.getVersion() != null ? model.getVersion() : System.currentTimeMillis());
            bdb.addPropertyValue("sharedVars", sharedVars);

            bdb.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            bdb.setFactoryMethodOnBean("getGroupTemplate", "beetlConfig");
            registry.registerBeanDefinition("groupTemplate", bdb.getBeanDefinition());
        }

        {
            if (this.model.getMappers() != null) {
                // 4.注册Mapper
                for (Model.Mapper mapper : this.model.getMappers()) {
                    BeetlSqlClassPathScanner scanner = new BeetlSqlClassPathScanner(registry);
                    scanner.setResourceLoader(this.model.getResourceLoader());
                    scanner.setSqlManagerFactoryBeanName(mapper.getDataSource() + "SqlManager");
                    scanner.setSuffix(mapper.getSuffix());
                    scanner.registerFilters();
                    scanner.scan(mapper.getPackages().split(","));
                }
            }
        }

        {
            // 扫描BeetlFunction
            BeetlTemplateElementScanner scaner = new BeetlTemplateElementScanner(registry);
            scaner.scan(model.getComponentScan());
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    }
}
